import {ElMessage, ElMessageBox} from 'element-plus'
// 递归找出所有面包屑并存下来
export const getAllBreadcrumbList = (menuList: any, result: Record<string, any> = {}, parent: any = []) => {
	for (const item of menuList) {
		if (parent[0]?.path) item.path = parent[parent.length - 1]?.path + '/' + item.path
		result[item.path] = [...parent, item]
		if (item.children) getAllBreadcrumbList(item.children, result, result[item.path])
	}
	return result
}

// 扁平化数组对象(主要用来处理路由菜单)
export function getFlatArr(menuList: any[]) {
	const newMenuList: any[] = JSON.parse(JSON.stringify(menuList))
	return newMenuList.reduce((pre: any, current: any) => {
		let flatArr = [...pre, current]
		if (current.children) flatArr = [...flatArr, ...getFlatArr(current.children)]
		return flatArr
	}, [])
}

/**
 * @description 使用递归，过滤出需要渲染在左侧菜单的列表（剔除 hidden == true 的菜单）
 * @param {Array} menuList 所有菜单列表
 * @return array
 * */
export function getShowMenuList(menuList: any) {
	const newMenuList: any = JSON.parse(JSON.stringify(menuList))
	return newMenuList.filter((item: any) => {
		item.children?.length && (item.children = getShowMenuList(item.children))
		return !item.hidden
	})
}

/**
 * hex颜色转rgb颜色
 * @param str 颜色值字符串
 * @returns 返回处理后的颜色值
 */
export function hexToRgb(str: any) {
	let hexs: any = ''
	const reg = /^#?[0-9A-Fa-f]{6}$/
	if (!reg.test(str)) return ElMessage.warning('输入错误的hex')
	str = str.replace('#', '')
	hexs = str.match(/../g)
	for (let i = 0; i < 3; i++) hexs[i] = parseInt(hexs[i], 16)
	return hexs
}

/**
 * rgb颜色转Hex颜色
 * @param r 代表红色
 * @param g 代表绿色
 * @param b 代表蓝色
 * @returns 返回处理后的颜色值
 */
export function rgbToHex(r: any, g: any, b: any) {
	const reg = /^\d{1,3}$/
	if (!reg.test(r) || !reg.test(g) || !reg.test(b)) return ElMessage.warning('输入错误的rgb颜色值')
	const hexs = [r.toString(16), g.toString(16), b.toString(16)]
	for (let i = 0; i < 3; i++) if (hexs[i].length === 1) hexs[i] = `0${hexs[i]}`
	return `#${hexs.join('')}`
}

/**
 * 变浅颜色值
 * @param color 颜色值字符串
 * @param level 加深的程度，限0-1之间
 * @returns 返回处理后的颜色值
 */
export function getLightColor(color: string, level: number) {
	const reg = /^#?[0-9A-Fa-f]{6}$/
	if (!reg.test(color)) return ElMessage.warning('输入错误的hex颜色值')
	const rgb = hexToRgb(color)
	for (let i = 0; i < 3; i++) rgb[i] = Math.round(255 * level + rgb[i] * (1 - level))
	return rgbToHex(rgb[0], rgb[1], rgb[2])
}

/**
 * 加深颜色值
 * @param color 颜色值字符串
 * @param level 加深的程度，限0-1之间
 * @returns 返回处理后的颜色值
 */
export function getDarkColor(color: string, level: number) {
	const reg = /^#?[0-9A-Fa-f]{6}$/
	if (!reg.test(color)) return ElMessage.warning('输入错误的hex颜色值')
	const rgb = hexToRgb(color)
	for (let i = 0; i < 3; i++) rgb[i] = Math.round(20.5 * level + rgb[i] * (1 - level))
	return rgbToHex(rgb[0], rgb[1], rgb[2])
}

/**
 * 递归查找替换
 * @param list 查询的数组
 * @param children 查询数组子节点的名称
 * @param field 查询的字段的名称
 * @param str 查询的字符串
 * @param dataName 添加数据的字段
 * @param data 添加的数据
 */
export function recursivelyAddData(list: any[], children: string, field: string, str: string, dataName: string, data: any) {
	// const newList = JSON.parse(JSON.stringify(list))
	return list.map(item => {
		// 克隆当前对象，以免修改原始数据
		const newItem = {...item}
		
		// 如果当前对象的id匹配目标id，则添加数据
		if (newItem[field] === str) {
			newItem[dataName] = data
		}
		
		// 如果当前对象具有children属性且是一个数组，则递归调用此函数
		if (newItem[children] && newItem[children].length > 0) {
			newItem[children] = recursivelyAddData(newItem[children], children, field, str, dataName, data)
		}
		
		return newItem
	})
}

/**
 * 解构赋值
 * @param list Object 需要赋值的数据项是一个对象
 * @param dataList 数据值也是一个对象
 * @param flag 是否全部转换成string类型
 */
export function deconstruction(list: any, dataList: any, flag = false) {
	for (const key in list) {
		for (const val in dataList) {
			if (key === val) {
				list[key] = flag ? dataList[key] === null || dataList[key] === undefined ? '' : String(dataList[key]) : dataList[key]
			}
		}
	}
	return list
}

/**
 * 通用删除方法
 * @param params 参数
 * @param flag 是否需要批量删除
 * @param url 删除的地址
 * @param otherUrl 重新执行的接口
 * @param name 中文名
 * @param nameValue 中文名字段
 * @constructor
 */
export function DeleteTableList(params: any, flag: boolean, url: Function, otherUrl: Function, name?: string, nameValue?: string) {
	ElMessageBox.confirm(flag ? '是否批量删除所选数据' : `是否删除${name}为${nameValue}的数据`,
		{
			confirmButtonText: '确定',
			cancelButtonText: '取消',
			type: 'warning'
		}
	).then(() => {
		url(params).then((res: any) => {
			if (res.code === 200) {
				ElMessage({
					type: 'success',
					message: '删除成功'
				})
				otherUrl()
			}
		})
	}).catch(() => {
	})
}

/**
 * 表单默认值
 * @param config 表单所有的配置项
 * @param form 表单绑定的值
 */
export function getDefaultValue(config: any, form: any) {
	const newForm = JSON.parse(JSON.stringify(form))
	config.forEach((e: any) => {
		if (e.dictKey === e.bind && e.dictList && e.dictList.length) {
			if (typeof newForm[e.bind] === 'string') {
				newForm[e.bind] = e.dictList.find((item: any) => item.isDefault === 'Y')?.dictValue
			} else {
				let arr: any = []
				e.dictList.forEach((e: any) => {
					if (e.isDefault === 'Y') {
						arr.push(e?.dictValue)
					}
				})
				newForm[e.bind] = arr
			}
		}
	})
	return newForm
}

/**
 * 构造树型结构数据
 * @param {*} data 数据源
 * @param {*} id id字段 默认 'id'
 * @param {*} parentId 父节点字段 默认 'parentId'
 * @param {*} children 孩子节点字段 默认 'children'
 */
export const handleTree = <T>(
	data: any[],
	id?: string,
	parentId?: string,
	children?: string
): T[] => {
	const config: {
		id: string;
		parentId: string;
		childrenList: string;
	} = {
		id: id || 'id',
		parentId: parentId || 'parentId',
		childrenList: children || 'children'
	}
	
	const childrenListMap: any = {}
	const nodeIds: any = {}
	const tree: T[] = []
	
	for (const d of data) {
		const parentId = d[config.parentId]
		if (childrenListMap[parentId] == null) {
			childrenListMap[parentId] = []
		}
		nodeIds[d[config.id]] = d
		childrenListMap[parentId].push(d)
	}
	
	for (const d of data) {
		const parentId = d[config.parentId]
		if (nodeIds[parentId] == null) {
			tree.push(d)
		}
	}
	const adaptToChildrenList = (o: any) => {
		if (childrenListMap[o[config.id]] !== null) {
			o[config.childrenList] = childrenListMap[o[config.id]]
		}
		if (o[config.childrenList]) {
			for (const c of o[config.childrenList]) {
				adaptToChildrenList(c)
			}
		}
	}
	for (const t of tree) {
		adaptToChildrenList(t)
	}
	return tree
}

export function treeToArray(tree: any) {
	let list: any = []
	
	// 递归函数用于遍历树
	function traverse(nodes: any) {
		nodes.forEach((node: any) => {
			list.push(node)
			if (node.children && node.children.length) {
				traverse(node.children)
			}
		})
	}
	
	traverse(tree)
	return list
}
